home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Panorama / Panorama - Disk 05B (1986)(Pacific North-West Amigas Club)[WB].zip / Panorama - Disk 05B (1986)(Pacific North-West Amigas Club)[WB].adf / uuencode.c < prev   
C/C++ Source or Header  |  1986-07-09  |  37KB  |  1,371 lines

  1.  ________________________________________________________________
  2.  
  3.  Message: 267759, 536 lines
  4.  Imported: 5:36pm PDT, Tue May 27/86
  5.  Subject: uuencode/uudecode sources (C and BASIC)
  6.  To: Unix-sources, unix-sources@brl-smoke.arpa
  7.  From: unix-sources-request%BRL.ARPA%BRL-SMOKE.ARPA%MIT-MULTICS.ARPA@UMich-MTS.Mailnet
  8.  
  9.  
  10.  # This is a shell archive.  Remove anything before this line,
  11.  # then unpack it by saving it in a file and typing "sh file".
  12.  #
  13.  # Wrapped by coulter at hplmac on Thu May 22 12:54:36 1986
  14.  #
  15.  # This archive contains:
  16.  #         README              uudecode.bas        uudecode.c          uuencode.1c
  17.  #         uuencode.c
  18.  
  19.  echo x - README
  20.  cat >README <<'@EOF'
  21.  
  22.  This shar file contains the C source for uuencode and uudecode.  It also
  23.  has the MSDOS BASIC code for uudecode.  There is a man page in
  24.  uuencode.1c.  P.S. - I didn't write any of it.
  25.  
  26.  -- Michael Coulter ...hplabs!coulter
  27.  @EOF
  28.  size=`wc -c <README`; if test $size -ne 222 ; then
  29.            echo ERROR: README is $size bytes but should be 222.
  30.  fi
  31.  
  32.  chmod 644 README
  33.  
  34.  echo x - uudecode.bas
  35.  cat >uudecode.bas <<'@EOF'
  36.  # Written  1:32 am  Feb 17, 1986 by rde@ukc.ac.uk in net.sources
  37.  # In Real Life: R.D.Eager at U of Kent at Canterbury, Canterbury, UK
  38.  # Subject: uudecode in MS-BASIC
  39.  
  40.  [food for line eater]
  41.  
  42.  There  has been some discussion about public domain versions of uudecode
  43.  for those souls who didn't get it in a distribution. I  thought  it  was
  44.  time  to post the updated version of uudecode in Microsoft BASIC; I have
  45.  made a minor change to cater for a variation in  coding  encountered  on
  46.  some uuencoded files.
  47.  
  48.  This  program  is  short  enough  that  it  can  be  typed in by hand if
  49.  necessary. I hope it is of some  use  to  micro  owners  without  direct
  50.  access to other uudecodes.
  51.  
  52.  ---------CUT HERE--------CUT HERE----------CUT HERE---------CUT HERE------
  53.  1000 DEFINT A-Z
  54.  1010 REM Trap filing errors
  55.  1020 ON ERROR GOTO 1600
  56.  1030 CLS
  57.  1040 LOCATE 5,11
  58.  1050 PRINT STRING$(40," ")
  59.  1060 LOCATE 5,11
  60.  1070 INPUT "Enter name of input file: ", INFILE$
  61.  1080 OPEN INFILE$ FOR INPUT AS #1
  62.  1090 LOCATE 8,10
  63.  1100 PRINT STRING$(40," ")
  64.  1110 LOCATE 8,10
  65.  1120 INPUT "Enter name of output file: ", OUTFILE$
  66.  1130 OPEN "R", #2,OUTFILE$, 1
  67.  1140 FIELD #2, 1 AS N$
  68.  1150 REM Search for header line
  69.  1160 LINE INPUT #1,A$
  70.  1170 IF LEFT$(A$,5) <>"begin" THEN 1160
  71.  1180 LOCATE 11,10
  72.  1190 PRINT "Header = ";A$
  73.  1200 SP = ASC(" ")
  74.  1210 DIM BUF(5000)
  75.  1220 P = 0
  76.  1230 REM Main loop
  77.  1240 LINE INPUT #1, A$
  78.  1250 P = 0
  79.  1260 COUNT = ASC(LEFT$(A$,1)) - SP
  80.  1270 IF COUNT <> 64 THEN 1290
  81.  1280 COUNT = 0
  82.  1290 IF COUNT = 0 THEN 1560
  83.  1300 ADJ = COUNT MOD 4
  84.  1310 FOR I = 2 TO LEN(A$) STEP 4
  85.  1320    X1 = ASC(MID$(A$,I,I)) - SP
  86.  1330    IF X1 <> 64 THEN 1350
  87.  1340    X1 = 0
  88.  1350    X2 = ASC(MID$(A$,I+1,I+1)) - SP
  89.  1360    IF X2 <> 64 THEN 1380
  90.  1370    X2 = 0
  91.  1380    X3 = ASC(MID$(A$,I+2,I+2)) - SP
  92.  1390    IF X3 <> 64 THEN 1410
  93.  1400    X3 = 0
  94.  1410    X4 = ASC(MID$(A$,I+3,I+3)) - SP
  95.  1420    IF X4 <> 64 THEN 1440
  96.  1430    X4 = 0
  97.  1440    P = P + 1
  98.  1450    BUF(P) = (X2\16) + (X1*4)
  99.  1460    P = P + 1
  100.  1470    BUF(P) = (X3\4) + ((X2 MOD 16) * 16)
  101.  1480    P = P + 1
  102.  1490    BUF(P) = X4 + ((X3 MOD 4) * 64)
  103.  1500 NEXT I
  104.  1510 FOR I = 1 TO P
  105.  1520   LSET N$ = CHR$(BUF(I))
  106.  1530   PUT #2
  107.  1540 NEXT I
  108.  1550 GOTO 1240
  109.  1560 END
  110.  1570 REM
  111.  1580 REM Error trapping routine for file handling
  112.  1590 REM
  113.  1600 IF ERL <> 1080 GOTO 1650          ' not input file problem
  114.  1610 LOCATE 22,20
  115.  1620 PRINT "Can't open input file"
  116.  1630 GOSUB 1780
  117.  1640 RESUME 1040
  118.  1650 IF ERL <> 1130 GOTO 1700          ' not output file problem
  119.  1660 LOCATE 22,20
  120.  1670 PRINT "Can't open output file"
  121.  1680 GOSUB 1780
  122.  1690 RESUME 1090
  123.  1700 IF ERL <> 1160 THEN 1770
  124.  1710 LOCATE 22,20
  125.  1720 PRINT "Header line not found"
  126.  1730 GOSUB 1780
  127.  1740 GOSUB 1780
  128.  1750 LOCATE 24,1
  129.  1760 END
  130.  1770 ERROR ERR
  131.  1780 FOR I = 1 TO 5000: NEXT I
  132.  1790 LOCATE 22,20
  133.  1800 PRINT STRING$(30," ")
  134.  1810 RETURN
  135.  TE 24,1
  136.  1760 END
  137.  1770 ERROR ERR
  138.  1780 FOR I = 1 TO 5000: NEXT I
  139.  1
  140.  ---------CUT HERE--------CUT HERE----------CUT HERE---------CUT HERE------
  141.  --
  142.             Bob Eager
  143.  
  144.             rde@ukc.UUCP
  145.             rde@ukc
  146.             ...!mcvax!ukc!rde
  147.  
  148.             Phone: +44 227 66822 ext 7589
  149.  # End of text from net.sources on hplabsc.UUCP
  150.  @EOF
  151.  size=`wc -c <uudecode.bas`; if test $size -ne 3106 ; then
  152.            echo ERROR: uudecode.bas is $size bytes but should be 3106.
  153.  fi
  154.  
  155.  chmod 644 uudecode.bas
  156.  
  157.  echo x - uudecode.c
  158.  cat >uudecode.c <<'@EOF'
  159.  #ifndef lint
  160.  static char sccsid[] = "@(#)uudecode.c  5.1 (Berkeley) 7/2/83";
  161.  #endif
  162.  
  163.  /*
  164.   * uudecode [input]
  165.   *
  166.   * create the specified file, decoding as you go.
  167.   * used with uuencode.
  168.   */
  169.  #include <stdio.h>
  170.  #include <pwd.h>
  171.  #include <sys/types.h>
  172.  #include <sys/stat.h>
  173.  
  174.  /* single character decode */
  175.  #define DEC(c)      (((c) - ' ') & 077)
  176.  
  177.  main(argc, argv)
  178.  char **argv;
  179.  {
  180.            FILE *in, *out;
  181.            struct stat sbuf;
  182.            int mode;
  183.            char dest[128];
  184.            char buf[80];
  185.  
  186.            /* optional input arg */
  187.            if (argc > 1) {
  188.                      if ((in = fopen(argv[1], "r")) == NULL) {
  189.                                perror(argv[1]);
  190.                                exit(1);
  191.                      }
  192.                      argv++; argc--;
  193.            } else
  194.                      in = stdin;
  195.  
  196.            if (argc != 1) {
  197.                      printf("Usage: uudecode [infile]\n");
  198.                      exit(2);
  199.            }
  200.  
  201.            /* search for header line */
  202.            for (;;) {
  203.                      if (fgets(buf, sizeof buf, in) == NULL) {
  204.                                fprintf(stderr, "No begin line\n");
  205.                                exit(3);
  206.                      }
  207.                      if (strncmp(buf, "begin ", 6) == 0)
  208.                                break;
  209.            }
  210.            sscanf(buf, "begin %o %s", &mode, dest);
  211.  
  212.            /* handle ~user/file format */
  213.            if (dest[0] == '~') {
  214.                      char *sl;
  215.                      struct passwd *getpwnam();
  216.                      char *index();
  217.                      struct passwd *user;
  218.                      char dnbuf[100];
  219.  
  220.                      sl = index(dest, '/');
  221.                      if (sl == NULL) {
  222.                                fprintf(stderr, "Illegal ~user\n");
  223.                                exit(3);
  224.                      }
  225.                      *sl++ = 0;
  226.                      user = getpwnam(dest+1);
  227.                      if (user == NULL) {
  228.                                fprintf(stderr, "No such user as %s\n", dest);
  229.                                exit(4);
  230.                      }
  231.                      strcpy(dnbuf, user->pw_dir);
  232.                      strcat(dnbuf, "/");
  233.                      strcat(dnbuf, sl);
  234.                      strcpy(dest, dnbuf);
  235.            }
  236.  
  237.            /* create output file */
  238.            out = fopen(dest, "w");
  239.            if (out == NULL) {
  240.                      perror(dest);
  241.                      exit(4);
  242.            }
  243.            chmod(dest, mode);
  244.  
  245.            decode(in, out);
  246.  
  247.            if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) {
  248.                      fprintf(stderr, "No end line\n");
  249.                      exit(5);
  250.            }
  251.            exit(0);
  252.  }
  253.  
  254.  /*
  255.   * copy from in to out, decoding as you go along.
  256.   */
  257.  decode(in, out)
  258.  FILE *in;
  259.  FILE *out;
  260.  {
  261.            char buf[80];
  262.            char *bp;
  263.            int n;
  264.  
  265.            for (;;) {
  266.                      /* for each input line */
  267.                      if (fgets(buf, sizeof buf, in) == NULL) {
  268.                                printf("Short file\n");
  269.                                exit(10);
  270.                      }
  271.                      n = DEC(buf[0]);
  272.                      if (n <= 0)
  273.                                break;
  274.  
  275.                      bp = &buf[1];
  276.                      while (n > 0) {
  277.                                outdec(bp, out, n);
  278.                                bp += 4;
  279.                                n -= 3;
  280.                      }
  281.            }
  282.  }
  283.  
  284.  /*
  285.   * output a group of 3 bytes (4 input characters).
  286.   * the input chars are pointed to by p, they are to
  287.   * be output to file f.  n is used to tell us not to
  288.   * output all of them at the end of the file.
  289.   */
  290.  outdec(p, f, n)
  291.  char *p;
  292.  FILE *f;
  293.  {
  294.            int c1, c2, c3;
  295.  
  296.            c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
  297.            c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
  298.            c3 = DEC(p[2]) << 6 | DEC(p[3]);
  299.            if (n >= 1)
  300.                      putc(c1, f);
  301.            if (n >= 2)
  302.                      putc(c2, f);
  303.            if (n >= 3)
  304.                      putc(c3, f);
  305.  }
  306.  
  307.  
  308.  /* fr: like read but stdio */
  309.  int
  310.  fr(fd, buf, cnt)
  311.  FILE *fd;
  312.  char *buf;
  313.  int cnt;
  314.  {
  315.            int c, i;
  316.  
  317.            for (i=0; i<cnt; i++) {
  318.                      c = getc(fd);
  319.                      if (c == EOF)
  320.                                return(i);
  321.                      buf[i] = c;
  322.            }
  323.            return (cnt);
  324.  }
  325.  
  326.  /*
  327.   * Return the ptr in sp at which the character c appears;
  328.   * NULL if not found
  329.   */
  330.  
  331.  #define   NULL      0
  332.  
  333.  char *
  334.  index(sp, c)
  335.  register char *sp, c;
  336.  {
  337.            do {
  338.                      if (*sp == c)
  339.                                return(sp);
  340.            } while (*sp++);
  341.            return(NULL);
  342.  }
  343.  @EOF
  344.  size=`wc -c <uudecode.c`; if test $size -ne 2949 ; then
  345.            echo ERROR: uudecode.c is $size bytes but should be 2949.
  346.  fi
  347.  
  348.  chmod 644 uudecode.c
  349.  
  350.  echo x - uuencode.1c
  351.  cat >uuencode.1c <<'@EOF'
  352.  .TH UUENCODE 1C "1 June 1980"
  353.  .UC 4
  354.  .SH NAME
  355.  uuencode,uudecode \- encode/decode a binary file for transmission via mail
  356.  .SH SYNOPSIS
  357.  .B uuencode
  358.  [ source ] remotedest |
  359.  .B mail
  360.  sys1!sys2!..!decode
  361.  .br
  362.  .B uudecode
  363.  [ file ]
  364.  .SH DESCRIPTION
  365.  .I Uuencode
  366.  and
  367.  .I uudecode
  368.  are used to send a binary file via uucp (or other) mail.
  369.  This combination can be used over indirect mail links
  370.  even when
  371.  .IR uusend (1C)
  372.  is not available.
  373.  .PP
  374.  .I Uuencode
  375.  takes the named source file (default standard input) and
  376.  produces an encoded version on the standard output.
  377.  The encoding uses only printing ASCII characters,
  378.  and includes the mode of the file and the
  379.  .I remotedest
  380.  for recreation on the remote system.
  381.  .PP
  382.  .I Uudecode
  383.  reads an encoded file,
  384.  strips off any leading and trailing lines added by mailers,
  385.  and recreates the original file with the specified mode and name.
  386.  .PP
  387.  The intent is that all mail to the user ``decode'' should be filtered
  388.  through the uudecode program.  This way the file is created automatically
  389.  without human intervention.
  390.  This is possible on the uucp network by either using
  391.  .I sendmail
  392.  or by making
  393.  .I rmail
  394.  be a link to
  395.  .I Mail
  396.  instead of
  397.  .I mail.
  398.  In each case, an alias must be created in a master file to get
  399.  the automatic invocation of uudecode.
  400.  .PP
  401.  If these facilities are not available, the file can be sent to a
  402.  user on the remote machine who can uudecode it manually.
  403.  .PP
  404.  The encode file has an ordinary text form and can be edited
  405.  by any text editor to change the mode or remote name.
  406.  .SH SEE\ ALSO
  407.  uuencode(5), uusend(1C), uucp(1C), uux(1C), mail(1)
  408.  .SH AUTHOR
  409.  Mark Horton
  410.  .SH BUGS
  411.  The file is expanded by 35% (3 bytes become 4 plus control information)
  412.  causing it to take longer to transmit.
  413.  .PP
  414.  The user on the remote system who is invoking
  415.  .I uudecode
  416.  (often
  417.  .I uucp)
  418.  must have write permission on the specified file.
  419.  @EOF
  420.  size=`wc -c <uuencode.1c`; if test $size -ne 1840 ; then
  421.            echo ERROR: uuencode.1c is $size bytes but should be 1840.
  422.  fi
  423.  
  424.  chmod 644 uuencode.1c
  425.  
  426.  echo x - uuencode.c
  427.  cat >uuencode.c <<'@EOF'
  428.  #ifndef lint
  429.  static char sccsid[] = "@(#)uuencode.c  5.1 (Berkeley) 7/2/83";
  430.  #endif
  431.  
  432.  /*
  433.   * uuencode [input] output
  434.   *
  435.   * Encode a file so it can be mailed to a remote system.
  436.   */
  437.  #include <stdio.h>
  438.  #include <sys/types.h>
  439.  #include <sys/stat.h>
  440.  
  441.  /* ENC is the basic 1 character encoding function to make a char printing */
  442.  #define ENC(c) (((c) & 077) + ' ')
  443.  
  444.  main(argc, argv)
  445.  char **argv;
  446.  {
  447.            FILE *in;
  448.            struct stat sbuf;
  449.            int mode;
  450.  
  451.            /* optional 1st argument */
  452.            if (argc > 2) {
  453.                      if ((in = fopen(argv[1], "r")) == NULL) {
  454.                                perror(argv[1]);
  455.                                exit(1);
  456.                      }
  457.                      argv++; argc--;
  458.            } else
  459.                      in = stdin;
  460.  
  461.            if (argc != 2) {
  462.                      printf("Usage: uuencode [infile] remotefile\n");
  463.                      exit(2);
  464.            }
  465.  
  466.            /* figure out the input file mode */
  467.            fstat(fileno(in), &sbuf);
  468.            mode = sbuf.st_mode & 0777;
  469.            printf("begin %o %s\n", mode, argv[1]);
  470.  
  471.            encode(in, stdout);
  472.  
  473.            printf("end\n");
  474.            exit(0);
  475.  }
  476.  
  477.  /*
  478.   * copy from in to out, encoding as you go along.
  479.   */
  480.  encode(in, out)
  481.  FILE *in;
  482.  FILE *out;
  483.  {
  484.            char buf[80];
  485.            int i, n;
  486.  
  487.            for (;;) {
  488.                      /* 1 (up to) 45 character line */
  489.                      n = fr(in, buf, 45);
  490.                      putc(ENC(n), out);
  491.  
  492.                      for (i=0; i<n; i += 3)
  493.                                outdec(&buf[i], out);
  494.  
  495.                      putc('\n', out);
  496.                      if (n <= 0)
  497.                                break;
  498.            }
  499.  }
  500.  
  501.  /*
  502.   * output one group of 3 bytes, pointed at by p, on file f.
  503.   */
  504.  outdec(p, f)
  505.  char *p;
  506.  FILE *f;
  507.  {
  508.            int c1, c2, c3, c4;
  509.  
  510.            c1 = *p >> 2;
  511.            c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
  512.            c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
  513.            c4 = p[2] & 077;
  514.            putc(ENC(c1), f);
  515.            putc(ENC(c2), f);
  516.            putc(ENC(c3), f);
  517.            putc(ENC(c4), f);
  518.  }
  519.  
  520.  /* fr: like read but stdio */
  521.  int
  522.  fr(fd, buf, cnt)
  523.  FILE *fd;
  524.  char *buf;
  525.  int cnt;
  526.  {
  527.            int c, i;
  528.  
  529.            for (i=0; i<cnt; i++) {
  530.                      c = getc(fd);
  531.                      if (c == EOF)
  532.                                return(i);
  533.                      buf[i] = c;
  534.            }
  535.            return (cnt);
  536.  }
  537.  @EOF
  538.  size=`wc -c <uuencode.c`; if test $size -ne 1707 ; then
  539.            echo ERROR: uuencode.c is $size bytes but should be 1707.
  540.  fi
  541.  
  542.  chmod 644 uuencode.c
  543.  
  544.  exit 0
  545.  ________________________________________________________________
  546.  
  547.  Message: 268753, 818 lines
  548.  Imported: 2:08am PDT, Thu May 29/86
  549.  Subject: Turbo $ C sources for MS-DOS uuen/decode
  550.  To: Unix-sources, unix-sources@brl-smoke.arpa
  551.  From: unix-sources-request%BRL.ARPA%BRL-SMOKE.ARPA%MIT-MULTICS.ARPA@UMich-MTS.Mailnet
  552.  
  553.  About 3 days ago I posted a request for code that implements uuencode and
  554.  uudecode under MS-DOS.  I received two very good responses.  One was source
  555.  code written in Turbo Pascal, the other in C.  Since I don't have a C compiler,
  556.  I used the Turbo sources (I have Turbo V3.0).  They work great.  Today I saw
  557.  the following message, so I thought I would go ahead and post the sources I
  558.  received.
  559.  
  560.  ( Note: now if I could only get code that would perform Unix's /bin/sh
  561.    under MS-DOS.... )
  562.  
  563.                                          - Cathy Fulton
  564.  
  565.  P.S. - To the person (henry) who mailed me the Turbo source code, I regret that
  566.         I inadvertantly lost your full name, so I am unable to give you credit
  567.         for the code.  However, I thank you for it very much, and I hope others
  568.         will find it as useful as I did.
  569.  
  570.  ************************************************************************
  571.  
  572.  
  573.  > This would be helpful to many other users.  We too do not have uuencode
  574.  > or uudecode.  Could someone post a version for MS-DOS to the net?
  575.  
  576.  
  577.  
  578.  > John Kalbach
  579.  > Penn State University
  580.  > Microcomputer Information and Support Center
  581.  > 103 Computation Center
  582.  > University Park, PA 16802
  583.  > (814) 863-4356
  584.  
  585.  >  ...!psuvax1!psuvm.bitnet!u0n
  586.  >  u0n%psuvm.bitnet@wscvm.arpa
  587.  
  588.  *********************************************************************
  589.  
  590.  
  591.            First, the Turbo Pascal version :
  592.  
  593.  
  594.  *********************************************************************
  595.  
  596.  
  597.  Here are the sources.  Using the programs is easy.  To use uuencode type
  598.  
  599.  >uuencode source target
  600.  
  601.  where source is the source file name, and target is the target file name.
  602.  If target has no extension, then uuencode will add the extension .uue.  If
  603.  you omit target, uuencode will use the source file name with the extension
  604.  .uue.
  605.  
  606.  To use uudecode, type
  607.  
  608.  >uudecode source
  609.  
  610.  where source is the name of the uuencoded file.  If you omit the extension on
  611.  source, uudecode will add .uue.
  612.  
  613.  Let me know if you need more help.
  614.  
  615.  regards,
  616.  henry
  617.  
  618.  
  619.  ----- cut here ----------------------------------------------
  620.  
  621.  
  622.  Program uuencode;
  623.  
  624.    CONST header = 'begin';
  625.          trailer = 'end';
  626.          defaultMode = '644';
  627.          defaultExtension = '.uue';
  628.          offset = 32;
  629.          charsPerLine = 60;
  630.          bytesPerHunk = 3;
  631.          sixBitMask = $3F;
  632.  
  633.    TYPE string80 = string[80];
  634.  
  635.    VAR infile: file of byte;
  636.        outfile: text;
  637.        infilename, outfilename, mode: string80;
  638.        lineLength, numbytes, bytesInLine: integer;
  639.        line: array [0..59] of char;
  640.        hunk: array [0..2] of byte;
  641.        chars: array [0..3] of byte;
  642.  
  643.  {  procedure debug;
  644.  
  645.      var i: integer;
  646.  
  647.      procedure writebin(x: byte);
  648.  
  649.        var i: integer;
  650.  
  651.        begin
  652.          for i := 1 to 8 do
  653.            begin
  654.              write ((x and $80) shr 7);
  655.              x := x shl 1
  656.            end;
  657.          write (' ')
  658.        end;
  659.  
  660.      begin
  661.        for i := 0 to 2 do writebin(hunk[i]);
  662.        writeln;
  663.        for i := 0 to 3 do writebin(chars[i]);
  664.        writeln;
  665.        for i := 0 to 3 do writebin(chars[i] and sixBitMask);
  666.        writeln
  667.      end;  }
  668.  
  669.    procedure Abort (message: string80);
  670.  
  671.      begin {abort}
  672.        writeln(message);
  673.        close(infile);
  674.        close(outfile);
  675.        halt
  676.      end; {abort}
  677.  
  678.    procedure Init;
  679.  
  680.      procedure GetFiles;
  681.  
  682.        VAR i: integer;
  683.            temp: string80;
  684.            ch: char;
  685.  
  686.        begin {GetFiles}
  687.          if ParamCount < 1 then abort ('No input file specified.');
  688.          infilename := ParamStr(1);
  689.          {$I-}
  690.          assign (infile, infilename);
  691.          reset (infile);
  692.          {$i+}
  693.          if IOResult > 0 then abort (concat ('Can''t open file ', infilename));
  694.          write('Uuencoding file ', infilename);
  695.  
  696.          i := pos('.', infilename);
  697.          if i = 0
  698.            then outfilename := infilename
  699.            else outfilename := copy (infilename, 1, pred(i));
  700.          mode := defaultMode;
  701.          if ParamCount > 1 then
  702.            for i := 2 to ParamCount do
  703.              begin
  704.                temp := Paramstr(i);
  705.                if temp[1] in ['0'..'9']
  706.                  then mode := temp
  707.                  else outfilename := temp
  708.              end;
  709.          if pos ('.', outfilename) = 0
  710.            then outfilename := concat(outfilename, defaultExtension);
  711.          assign (outfile, outfilename);
  712.          writeln (' to file ', outfilename, '.');
  713.  
  714.          {$i-}
  715.          reset(outfile);
  716.          {$i+}
  717.          if IOresult = 0 then
  718.            begin
  719.              Write ('Overwrite current ', outfilename, '? [Y/N] ');
  720.              repeat
  721.                read (kbd, ch);
  722.                ch := Upcase(ch)
  723.              until ch in ['Y', 'N'];
  724.              writeln (ch);
  725.              if ch = 'N' then abort(concat (outfilename, ' not overwritten.'))
  726.            end;
  727.          close(outfile);
  728.  
  729.          {$i-}
  730.          rewrite(outfile);
  731.          {$i+}
  732.          if ioresult > 0 then abort(concat('Can''t open ', outfilename));
  733.        end; {getfiles}
  734.  
  735.      begin {Init}
  736.        GetFiles;
  737.        bytesInLine := 0;
  738.        lineLength := 0;
  739.        numbytes := 0;
  740.        writeln (outfile, header, ' ', mode, ' ', infilename);
  741.      end; {init}
  742.  
  743.    procedure FlushLine;
  744.  
  745.      VAR i: integer;
  746.  
  747.      procedure writeout(ch: char);
  748.  
  749.        begin {writeout}
  750.          if ch = ' ' then write(outfile, '`')
  751.                      else write(outfile, ch)
  752.        end; {writeout}
  753.  
  754.      begin {FlushLine}
  755.        write ('.');
  756.        writeout(chr(bytesInLine + offset));
  757.        for i := 0 to pred(lineLength) do
  758.          writeout(line[i]);
  759.        writeln (outfile);
  760.        lineLength := 0;
  761.        bytesInLine := 0
  762.      end; {FlushLine}
  763.  
  764.    procedure FlushHunk;
  765.  
  766.      VAR i: integer;
  767.  
  768.      begin {FlushHunk}
  769.        if lineLength = charsPerLine then FlushLine;
  770.        chars[0] := hunk[0] shr 2;
  771.        chars[1] := (hunk[0] shl 4) + (hunk[1] shr 4);
  772.        chars[2] := (hunk[1] shl 2) + (hunk[2] shr 6);
  773.        chars[3] := hunk[2] and sixBitMask;
  774.        {debug;}
  775.        for i := 0 to 3 do
  776.          begin
  777.            line[lineLength] := chr((chars[i] and sixBitMask) + offset);
  778.            {write(line[linelength]:2);}
  779.            lineLength := succ(lineLength)
  780.          end;
  781.        {writeln;}
  782.        bytesInLine := bytesInLine + numbytes;
  783.        numbytes := 0
  784.      end; {FlushHunk}
  785.  
  786.    procedure encode1;
  787.  
  788.      begin {encode1};
  789.        if numbytes = bytesperhunk then flushhunk;
  790.        read (infile, hunk[numbytes]);
  791.        numbytes := succ(numbytes)
  792.      end; {encode1}
  793.  
  794.    procedure terminate;
  795.  
  796.      begin {terminate}
  797.        if numbytes > 0 then flushhunk;
  798.        if lineLength > 0
  799.          then
  800.            begin
  801.              flushLine;
  802.              flushLine;
  803.            end
  804.          else flushline;
  805.        writeln (outfile, trailer);
  806.        close (outfile);
  807.        close (infile);
  808.      end; {terminate}
  809.  
  810.  
  811.    begin {uuencode}
  812.      init;
  813.      while not eof (infile) do encode1;
  814.      terminate
  815.    end. {uuencode}
  816.  
  817.  
  818.    ----- cut here ----------------------------------------------
  819.  
  820.  
  821.  program uudecode;
  822.  
  823.    CONST defaultSuffix = '.uue';
  824.          offset = 32;
  825.  
  826.    TYPE string80 = string[80];
  827.  
  828.    VAR infile: text;
  829.        outfile: file of byte;
  830.        lineNum: integer;
  831.        line: string80;
  832.  
  833.    procedure Abort(message: string80);
  834.  
  835.      begin {abort}
  836.        writeln;
  837.        if lineNum > 0 then write('Line ', lineNum, ': ');
  838.        writeln(message);
  839.        halt
  840.      end; {Abort}
  841.  
  842.    procedure NextLine(var s: string80);
  843.  
  844.      begin {NextLine}
  845.        LineNum := succ(LineNum);
  846.        write('.');
  847.        readln(infile, s)
  848.      end; {NextLine}
  849.  
  850.    procedure Init;
  851.  
  852.      procedure GetInFile;
  853.  
  854.        VAR infilename: string80;
  855.  
  856.        begin {GetInFile}
  857.          if ParamCount = 0 then abort ('Usage: uudecode <filename>');
  858.          infilename := ParamStr(1);
  859.          if pos('.', infilename) = 0
  860.            then infilename := concat(infilename, defaultSuffix);
  861.          assign(infile, infilename);
  862.          {$i-}
  863.          reset(infile);
  864.          {$i+}
  865.          if IOresult > 0 then abort (concat('Can''t open ', infilename));
  866.          writeln ('Decoding ', infilename)
  867.        end; {GetInFile}
  868.  
  869.      procedure GetOutFile;
  870.  
  871.        var header, mode, outfilename: string80;
  872.            ch: char;
  873.  
  874.        procedure ParseHeader;
  875.  
  876.          VAR index: integer;
  877.  
  878.          Procedure NextWord(var word:string80; var index: integer);
  879.  
  880.            begin {nextword}
  881.              word := '';
  882.              while header[index] = ' ' do
  883.                begin
  884.                  index := succ(index);
  885.                  if index > length(header) then abort ('Incomplete header')
  886.                end;
  887.              while header[index] <> ' ' do
  888.                begin
  889.                  word := concat(word, header[index]);
  890.                  index := succ(index)
  891.                end
  892.            end; {NextWord}
  893.  
  894.          begin {ParseHeader}
  895.            header := concat(header, ' ');
  896.            index := 7;
  897.            NextWord(mode, index);
  898.            NextWord(outfilename, index)
  899.          end; {ParseHeader}
  900.  
  901.        begin {GetOutFile}
  902.          if eof(infile) then abort('Nothing to decode.');
  903.          NextLine (header);
  904.          while not ((copy(header, 1, 6) = 'begin ') or eof(infile)) do
  905.            NextLine(header);
  906.          writeln;
  907.          if eof(infile) then abort('Nothing to decode.');
  908.          ParseHeader;
  909.          assign(outfile, outfilename);
  910.          writeln ('Destination is ', outfilename);
  911.          {$i-}
  912.          reset(outfile);
  913.          {$i+}
  914.          if IOresult = 0 then
  915.            begin
  916.              write ('Overwrite current ', outfilename, '? [Y/N] ');
  917.              repeat
  918.                read (kbd, ch);
  919.                ch := UpCase(ch)
  920.              until ch in ['Y', 'N'];
  921.              writeln(ch);
  922.              if ch = 'N' then abort ('Overwrite cancelled.')
  923.            end;
  924.          rewrite (outfile);
  925.        end; {GetOutFile}
  926.  
  927.      begin {init}
  928.        lineNum := 0;
  929.        GetInFile;
  930.        GetOutFile;
  931.      end; { init}
  932.  
  933.    Function CheckLine: boolean;
  934.  
  935.      begin {CheckLine}
  936.        if line = '' then abort ('Blank line in file');
  937.        CheckLine := not (line[1] in [' ', '`'])
  938.      end; {CheckLine}
  939.  
  940.  
  941.    procedure DecodeLine;
  942.  
  943.      VAR lineIndex, byteNum, count, i: integer;
  944.          chars: array [0..3] of byte;
  945.          hunk: array [0..2] of byte;
  946.  
  947.  {    procedure debug;
  948.  
  949.        var i: integer;
  950.  
  951.        procedure writebin(x: byte);
  952.  
  953.          var i: integer;
  954.  
  955.          begin
  956.            for i := 1 to 8 do
  957.              begin
  958.                write ((x and $80) shr 7);
  959.                x := x shl 1
  960.              end;
  961.            write (' ')
  962.          end;
  963.  
  964.        begin
  965.          writeln;
  966.          for i := 0 to 3 do writebin(chars[i]);
  967.          writeln;
  968.          for i := 0 to 2 do writebin(hunk[i]);
  969.          writeln
  970.        end;      }
  971.  
  972.      function nextch: char;
  973.  
  974.        begin {nextch}
  975.          lineIndex := succ(lineIndex);
  976.          if lineIndex > length(line) then abort('Line too short.');
  977.          if not (line[lineindex] in [' '..'`'])
  978.            then abort('Illegal character in line.');
  979.  {        write(line[lineindex]:2);}
  980.          if line[lineindex] = '`' then nextch := ' '
  981.                                    else nextch := line[lineIndex]
  982.        end; {nextch}
  983.  
  984.      procedure DecodeByte;
  985.  
  986.        procedure GetNextHunk;
  987.  
  988.          VAR i: integer;
  989.  
  990.          begin {GetNextHunk}
  991.            for i := 0 to 3 do chars[i] := ord(nextch) - offset;
  992.            hunk[0] := (chars[0] shl 2) + (chars[1] shr 4);
  993.            hunk[1] := (chars[1] shl 4) + (chars[2] shr 2);
  994.            hunk[2] := (chars[2] shl 6) + chars[3];
  995.            byteNum := 0  {;
  996.            debug          }
  997.          end; {GetNextHunk}
  998.  
  999.        begin {DecodeByte}
  1000.          if byteNum = 3 then GetNextHunk;
  1001.          write (outfile, hunk[byteNum]);
  1002.          {writeln(bytenum, ' ', hunk[byteNum]);}
  1003.          byteNum := succ(byteNum)
  1004.        end; {DecodeByte}
  1005.  
  1006.      begin {DecodeLine}
  1007.        lineIndex := 0;
  1008.        byteNum := 3;
  1009.        count := (ord(nextch) - offset);
  1010.        for i := 1 to count do DecodeByte
  1011.      end; {DecodeLine}
  1012.  
  1013.    procedure terminate;
  1014.  
  1015.      var trailer: string80;
  1016.  
  1017.      begin {terminate}
  1018.        if eof(infile) then abort ('Abnormal end.');
  1019.        NextLine (trailer);
  1020.        if length (trailer) < 3 then abort ('Abnormal end.');
  1021.        if copy (trailer, 1, 3) <> 'end' then abort ('Abnormal end.');
  1022.        close (infile);
  1023.        close (outfile)
  1024.      end;
  1025.  
  1026.    begin {uudecode}
  1027.      init;
  1028.      NextLine(line);
  1029.      while CheckLine do
  1030.        begin
  1031.          DecodeLine;
  1032.          NextLine(line)
  1033.        end;
  1034.      terminate
  1035.    end.
  1036.  
  1037.  **************************************************************************
  1038.  
  1039.  
  1040.            ...and now the C version:
  1041.  
  1042.  
  1043.  *************************************************************************
  1044.  
  1045.  
  1046.  uudecode and uuencode are easily implemented under MSDOS as well.  Here
  1047.  are the sources for Microsoft C v3.0, but if you have another kind of C
  1048.  compiler, there should be perhaps only 1 change -- the output file of
  1049.  uudecode and the input file of uuencode must be in binary format.
  1050.  (ie.  binary files, like .EXE files may have byte patterns that are the
  1051.  same as ^Z, which signals end-of-file in non-binary (text) mode).
  1052.  
  1053.  If you need more info, write back.  Note that the included files are
  1054.  *not* in "shar" format -- you will have to use an editor to cut the
  1055.  files out.
  1056.  
  1057.            Don Kneller
  1058.  UUCP:     ...ucbvax!ucsfcgl!kneller
  1059.  ARPA:     kneller@ucsf-cgl.ARPA
  1060.  BITNET:   kneller@ucsfcgl.BITNET
  1061.  
  1062.  ====================================================
  1063.  #ifndef lint
  1064.  static char sccsid[] = "@(#)uuencode.c  5.1 (Berkeley) 7/2/83";
  1065.  #endif
  1066.  
  1067.  /*
  1068.   * uuencode [input] output
  1069.   *
  1070.   * Encode a file so it can be mailed to a remote system.
  1071.   */
  1072.  #include <stdio.h>
  1073.  #include <sys/types.h>
  1074.  #include <sys/stat.h>
  1075.  
  1076.  /* ENC is the basic 1 character encoding function to make a char printing */
  1077.  #define ENC(c) (((c) & 077) + ' ')
  1078.  
  1079.  main(argc, argv)
  1080.  char **argv;
  1081.  {
  1082.            FILE *in;
  1083.            struct stat sbuf;
  1084.            int mode;
  1085.  
  1086.            /* optional 1st argument */
  1087.            if (argc > 2) {
  1088.  #ifdef MSDOS
  1089.                      /* Use binary mode */
  1090.                      if ((in = fopen(argv[1], "rb")) == NULL) {
  1091.  #else
  1092.                      if ((in = fopen(argv[1], "r")) == NULL) {
  1093.  #endif
  1094.                                perror(argv[1]);
  1095.                                exit(1);
  1096.                      }
  1097.                      argv++; argc--;
  1098.            } else
  1099.                      in = stdin;
  1100.  
  1101.            if (argc != 2) {
  1102.                      printf("Usage: uuencode [infile] remotefile\n");
  1103.                      exit(2);
  1104.            }
  1105.  
  1106.            /* figure out the input file mode */
  1107.            fstat(fileno(in), &sbuf);
  1108.            mode = sbuf.st_mode & 0777;
  1109.            printf("begin %o %s\n", mode, argv[1]);
  1110.  
  1111.            encode(in, stdout);
  1112.  
  1113.            printf("end\n");
  1114.            exit(0);
  1115.  }
  1116.  
  1117.  /*
  1118.   * copy from in to out, encoding as you go along.
  1119.   */
  1120.  encode(in, out)
  1121.  FILE *in;
  1122.  FILE *out;
  1123.  {
  1124.            char buf[80];
  1125.            int i, n;
  1126.  
  1127.            for (;;) {
  1128.                      /* 1 (up to) 45 character line */
  1129.                      n = fr(in, buf, 45);
  1130.                      putc(ENC(n), out);
  1131.  
  1132.                      for (i=0; i<n; i += 3)
  1133.                                outdec(&buf[i], out);
  1134.  
  1135.                      putc('\n', out);
  1136.                      if (n <= 0)
  1137.                                break;
  1138.            }
  1139.  }
  1140.  
  1141.  /*
  1142.   * output one group of 3 bytes, pointed at by p, on file f.
  1143.   */
  1144.  outdec(p, f)
  1145.  char *p;
  1146.  FILE *f;
  1147.  {
  1148.            int c1, c2, c3, c4;
  1149.  
  1150.            c1 = *p >> 2;
  1151.            c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
  1152.            c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
  1153.            c4 = p[2] & 077;
  1154.            putc(ENC(c1), f);
  1155.            putc(ENC(c2), f);
  1156.            putc(ENC(c3), f);
  1157.            putc(ENC(c4), f);
  1158.  }
  1159.  
  1160.  /* fr: like read but stdio */
  1161.  int
  1162.  fr(fd, buf, cnt)
  1163.  FILE *fd;
  1164.  char *buf;
  1165.  int cnt;
  1166.  {
  1167.            int c, i;
  1168.  
  1169.            for (i=0; i<cnt; i++) {
  1170.                      c = getc(fd);
  1171.                      if (c == EOF)
  1172.                                return(i);
  1173.                      buf[i] = c;
  1174.            }
  1175.            return (cnt);
  1176.  }
  1177.  ====================================================
  1178.  #ifndef lint
  1179.  static char sccsid[] = "@(#)uudecode.c  5.1 (Berkeley) 7/2/83";
  1180.  #endif
  1181.  
  1182.  /*
  1183.   * uudecode [input]
  1184.   *
  1185.   * create the specified file, decoding as you go.
  1186.   * used with uuencode.
  1187.   */
  1188.  #include <stdio.h>
  1189.  #ifndef MSDOS
  1190.  #include <pwd.h>
  1191.  #endif
  1192.  #include <sys/types.h>
  1193.  #include <sys/stat.h>
  1194.  
  1195.  /* single character decode */
  1196.  #define DEC(c)      (((c) - ' ') & 077)
  1197.  
  1198.  main(argc, argv)
  1199.  char **argv;
  1200.  {
  1201.            FILE *in, *out;
  1202.            struct stat sbuf;
  1203.            int mode;
  1204.            char dest[128];
  1205.            char buf[80];
  1206.  
  1207.            /* optional input arg */
  1208.            if (argc > 1) {
  1209.                      if ((in = fopen(argv[1], "r")) == NULL) {
  1210.                                perror(argv[1]);
  1211.                                exit(1);
  1212.                      }
  1213.                      argv++; argc--;
  1214.            } else
  1215.                      in = stdin;
  1216.  
  1217.            if (argc != 1) {
  1218.                      printf("Usage: uudecode [infile]\n");
  1219.                      exit(2);
  1220.            }
  1221.  
  1222.            /* search for header line */
  1223.            for (;;) {
  1224.                      if (fgets(buf, sizeof buf, in) == NULL) {
  1225.                                fprintf(stderr, "No begin line\n");
  1226.                                exit(3);
  1227.                      }
  1228.                      if (strncmp(buf, "begin ", 6) == 0)
  1229.                                break;
  1230.            }
  1231.            sscanf(buf, "begin %o %s", &mode, dest);
  1232.  
  1233.            /* handle ~user/file format */
  1234.  #ifndef MSDOS
  1235.            if (dest[0] == '~') {
  1236.                      char *sl;
  1237.                      struct passwd *getpwnam();
  1238.                      char *index();
  1239.                      struct passwd *user;
  1240.                      char dnbuf[100];
  1241.  
  1242.                      sl = index(dest, '/');
  1243.                      if (sl == NULL) {
  1244.                                fprintf(stderr, "Illegal ~user\n");
  1245.                                exit(3);
  1246.                      }
  1247.                      *sl++ = 0;
  1248.                      user = getpwnam(dest+1);
  1249.                      if (user == NULL) {
  1250.                                fprintf(stderr, "No such user as %s\n", dest);
  1251.                                exit(4);
  1252.                      }
  1253.                      strcpy(dnbuf, user->pw_dir);
  1254.                      strcat(dnbuf, "/");
  1255.                      strcat(dnbuf, sl);
  1256.                      strcpy(dest, dnbuf);
  1257.            }
  1258.  #endif
  1259.  
  1260.            /* create output file */
  1261.  #ifdef MSDOS
  1262.            /* binary output file */
  1263.            out = fopen(dest, "wb");
  1264.  #else
  1265.            out = fopen(dest, "w");
  1266.  #endif
  1267.            if (out == NULL) {
  1268.                      perror(dest);
  1269.                      exit(4);
  1270.            }
  1271.            chmod(dest, mode);
  1272.  
  1273.            decode(in, out);
  1274.  
  1275.            if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) {
  1276.                      fprintf(stderr, "No end line\n");
  1277.                      exit(5);
  1278.            }
  1279.            exit(0);
  1280.  }
  1281.  
  1282.  /*
  1283.   * copy from in to out, decoding as you go along.
  1284.   */
  1285.  decode(in, out)
  1286.  FILE *in;
  1287.  FILE *out;
  1288.  {
  1289.            char buf[80];
  1290.            char *bp;
  1291.            int n;
  1292.  
  1293.            for (;;) {
  1294.                      /* for each input line */
  1295.                      if (fgets(buf, sizeof buf, in) == NULL) {
  1296.                                printf("Short file\n");
  1297.                                exit(10);
  1298.                      }
  1299.                      n = DEC(buf[0]);
  1300.                      if (n <= 0)
  1301.                                break;
  1302.  
  1303.                      bp = &buf[1];
  1304.                      while (n > 0) {
  1305.                                outdec(bp, out, n);
  1306.                                bp += 4;
  1307.                                n -= 3;
  1308.                      }
  1309.            }
  1310.  }
  1311.  
  1312.  /*
  1313.   * output a group of 3 bytes (4 input characters).
  1314.   * the input chars are pointed to by p, they are to
  1315.   * be output to file f.  n is used to tell us not to
  1316.   * output all of them at the end of the file.
  1317.   */
  1318.  outdec(p, f, n)
  1319.  char *p;
  1320.  FILE *f;
  1321.  {
  1322.            int c1, c2, c3;
  1323.  
  1324.            c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
  1325.            c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
  1326.            c3 = DEC(p[2]) << 6 | DEC(p[3]);
  1327.            if (n >= 1)
  1328.                      putc(c1, f);
  1329.            if (n >= 2)
  1330.                      putc(c2, f);
  1331.            if (n >= 3)
  1332.                      putc(c3, f);
  1333.  }
  1334.  
  1335.  
  1336.  /* fr: like read but stdio */
  1337.  int
  1338.  fr(fd, buf, cnt)
  1339.  FILE *fd;
  1340.  char *buf;
  1341.  int cnt;
  1342.  {
  1343.            int c, i;
  1344.  
  1345.            for (i=0; i<cnt; i++) {
  1346.                      c = getc(fd);
  1347.                      if (c == EOF)
  1348.                                return(i);
  1349.                      buf[i] = c;
  1350.            }
  1351.            return (cnt);
  1352.  }
  1353.  
  1354.  /*
  1355.   * Return the ptr in sp at which the character c appears;
  1356.   * NULL if not found
  1357.   */
  1358.  
  1359.  #define   NULL      0
  1360.  
  1361.  char *
  1362.  index(sp, c)
  1363.  register char *sp, c;
  1364.  {
  1365.            do {
  1366.                      if (*sp == c)
  1367.                                return(sp);
  1368.            } while (*sp++);
  1369.            return(NULL);
  1370.  }
  1371.